package com.mrd.gtimp.base.service;

import com.mrd.base.BaseBiz;
import com.mrd.exception.QueryException;
import com.mrd.exception.SaveException;
import com.mrd.framework.ui.filter.Filter;
import com.mrd.framework.ui.filter.SearchRule;
import com.mrd.framework.ui.filter.SearchRuleOption;
import com.mrd.gtimp.base.entity.Module;
import com.mrd.gtimp.base.entity.Permissions;
import com.mrd.gtimp.base.entity.Role;
import com.mrd.gtimp.base.entity.User;
import com.mrd.gtimp.base.repository.ModuleDao;
import com.mrd.gtimp.base.repository.RoleDao;
import com.mrd.spring.repository.BaseRepository;
import com.mrd.util.CollectionUtil;
import com.mrd.util.IFilter;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

/**
 * <p>
 * application name: gtimp
 * <p>
 * copyright: Copyright@2012 明睿达科技有限公司
 */

/**
 * @author qiul
 */
@Service
public class RoleBiz extends BaseBiz<Role> {
	private static final Logger	logger			= LoggerFactory.getLogger(RoleBiz.class);
	@Resource
	private ModuleDao			moduleDao;
	@Resource
	private RoleDao				roleDao;
	@Resource
	private PermissionsBiz		permissionsBiz;

	private ModuleFilter		moduleFilter	= new ModuleFilter();

	@Resource
	// 该处指定注入baseDao的dao对象
	@Qualifier("roleDao")
	public void setBaseRepository(BaseRepository<Role, String> baseRepository) {
		super.baseRepository = baseRepository;
	}

	/*
	 * (non-Javadoc)
	 * @see com.mrd.gtimp.base.biz.RoleBiz#findRoleModule(java.lang.String)
	 */
	public List<Module> findRoleModule(final String roleId,final String moduleId) throws Exception {
		Role role = super.findEntityById(roleId);
		List<Module> modules = role.getModules();
		List<Module> manageModule = role.getManageModules();
		IFilter<Module> moduleIf = new IFilter<Module>() {

			public boolean filter(Module m) {
				boolean stateOk = "0".equals(m.getState());// 已经启用
				if(moduleId == null) {
					return m.getParent() == null && stateOk;
				} else if(m.getParent() != null) {
					return moduleId.equals(m.getParent().getId()) && stateOk;
				} else {
					return false;
				}
			}
		};
		manageModule = CollectionUtil.list(manageModule, moduleIf);
		modules = CollectionUtil.list(modules, moduleIf);
		if(modules == null || modules.size() == 0) {
			return manageModule;
		}
		if(manageModule != null) {
			for(Module module : manageModule) {
				if(modules.contains(module)) {
					module.setChecked(true);
				}
			}
		}
		return manageModule;
	}

	public List<Module> findRoleManageModule(String roleId,String moduleId) throws Exception {
		try {
			Role role = super.findEntityById(roleId);
			if(role == null) {
				return null;
			} else {
				Filter filter = new Filter();
				if(StringUtils.isEmpty(moduleId)) {
					filter.addRule(new SearchRule("parent", SearchRuleOption.inl, ""));
				} else {
					filter.addRule(new SearchRule("parent.id", SearchRuleOption.eq, moduleId));
				}
				filter.addRule(new SearchRule("state", SearchRuleOption.eq, "0"));
				Sort.Order order = new Sort.Order("name");
				List<Module> modules = moduleDao.findEntityByFilter(0, 0, filter, order);
				List<Module> roleManageModules = role.getManageModules();
				roleManageModules = CollectionUtil.list(roleManageModules, moduleFilter);
				if(roleManageModules != null) {
					for(Module module : modules) {
						if(roleManageModules.contains(module)) {
							module.setChecked(true);
						}
					}
				}
				return modules;
			}
		} catch (QueryException e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<Permissions> findRoleModulePermissions(String roleId,String moduleId)
	        throws Exception {
		//// TODO: 2016/8/17
		try {
			List<Permissions> havePms = null;// roleDao.findRoleModulePermissions(roleId, moduleId);
			List<Permissions> managePms = null;// roleDao.findRoleManageModulePermissions(roleId,
			                                   // moduleId);
			if(managePms == null) {
				return null;
			}
			if(havePms != null && havePms.size() != 0) {
				for(Permissions permissions : managePms) {
					if(havePms.contains(permissions)) {
						permissions.setChecked(true);
					}
				}
			}
			Collections.sort(managePms);
			return managePms;
		} catch (Exception e) {
			throw e;
		}
	}

	public List<Permissions> findRoleManageModulePermissions(String roleId,String moduleId)
	        throws Exception {
		try {// TODO: 2016/8/17
			List<Permissions> havePms = null;// roleDao.findRoleManageModulePermissions(roleId,
			                                 // moduleId);
			Filter filter = new Filter();
			filter.addRule(new SearchRule("module.id", SearchRuleOption.eq, moduleId));
			List<Permissions> allModulePermissions = permissionsBiz
			        .findEntityByFilter(0, 0, filter, null);
			if(allModulePermissions == null) {
				return null;
			}
			if(havePms != null && havePms.size() != 0) {
				for(Permissions permissions : allModulePermissions) {
					if(havePms.contains(permissions)) {
						permissions.setChecked(true);
					}
				}
			}
			// Collections.sort(allModulePermissions);
			return allModulePermissions;
		} catch (Exception e) {
			throw e;
		}
	}

	public Role saveRoleModule(Role role) throws SaveException, QueryException {
		Role roleTmp = findEntityById(role.getId());
		roleTmp.setModules(role.getModules());
		saveOrupdateEntity(roleTmp);
		return roleTmp;
	}

	public Role saveRoleManageModule(Role role) throws SaveException, QueryException {
		Role roleTmp = findEntityById(role.getId());
		roleTmp.setManageModules(role.getManageModules());
		saveOrupdateEntity(roleTmp);
		return roleTmp;
	}

	public Role saveRoleManagePermissions(Role role) throws Exception {
		Role roleTmp = findEntityById(role.getId());
		roleTmp.setManagePermissions(role.getManagePermissions());
		saveOrupdateEntity(roleTmp);
		return role;
	}

	public Role saveRolePermissions(Role role) throws Exception {
		Role roleTmp = findEntityById(role.getId());
		roleTmp.setPermissions(role.getPermissions());
		saveOrupdateEntity(roleTmp);
		return role;
	}

	public Role saveRoleUsers(Role role) throws Exception {
		Role roleTmp = findEntityById(role.getId());
		List<String> delUsers = new ArrayList<String>();
		Map<String, String> mapDel = new HashMap<String, String>();
		Map<String, String> mapSam = new HashMap<String, String>();
		List<User> addUsers = new ArrayList<User>();
		for(User u : role.getUsers()) {
			if(u.getChecked()) {
				addUsers.add(u);
				mapSam.put(u.getId(), "0");
			} else {
				delUsers.add(u.getId());
				mapDel.put(u.getId(), "0");
			}
		}
		for(User u : roleTmp.getUsers()) {
			if(!mapDel.containsKey(u.getId()) && !mapSam.containsKey(u.getId())) {
				addUsers.add(u);
			}
		}
		roleTmp.setUsers(addUsers);
		saveOrupdateEntity(roleTmp);
		return role;
	}

	/**
	 * 通过用户账号使用sql的方式查询角色集合(解决部分代码位置无法获取到hibernate session的问题)
	 * @param account
	 *            账号
	 * @return 角色集合，账号为空时返回一个空集合
	 */
	public List<Role> findRolesByAcoountUseSql(String account) {
		List<Role> roles = new ArrayList<>();
		if(StringUtils.isEmpty(account)) {
			return roles;
		}
		String sql = "select t.id,t.name from t_sys_role t join t_sys_role_user ru on t.id = ru.role_id join t_sys_user u on ru.user_id = u.u_id where u.u_account = :account and t.r_state = '0'";
		Map<String, Object> parameters = new HashMap<>();
		parameters.put("account", account);
		try {
			List<Object> rs = baseRepository.findEntityBySql(sql, 0, 1000, parameters);
			for(Object r : rs) {
				Object[] o = (Object[]) r;
				Role role = new Role();
				role.setId((String) o[0]);
				role.setName((String) o[1]);
				roles.add(role);
			}
		} catch (QueryException e) {
			logger.error("通过用户账号查询权限集合是发生错误", e);
			return roles;
		}
		return roles;
	}

	/**
	 * 这个方法的判断依据是在建立3.0角色时，3.0角色比2.0同功能的角色多一个-3.0的后缀。
	 */
	public List<Role> v20RolesConvertToV30(List<Role> v20Roles) {
		List<String> v30RoleNameList = new ArrayList<>();
		List<Role> v30RoleList = new ArrayList<>();
		for(Role v20Role : v20Roles) {
			String roleName = v20Role.getName();
			if(!roleName.contains("-3.0")) {
				v30RoleNameList.add(roleName + "-3.0");
			} else {
				v30RoleList.add(v20Role);
			}
			if("admin".equals(roleName)) {
				v30RoleList.add(v20Role);
			}
		}
		if(v30RoleNameList.size() == 0) {
			return v20Roles;
		}
		v30RoleList.addAll(roleDao.findByNameIn(v30RoleNameList));
		if(v30RoleList.size() == 0) {
			return v20Roles;
		}
		return v30RoleList;
	}

	private class ModuleFilter implements IFilter<Module> {

		public boolean filter(Module m) {
			if(m == null) {
				return false;
			}
			if("0".equals(m.getState())) {
				return true;
			} else {
				return false;
			}
		}

	}

}
